package at.fhhagenberg.hydrac.java.sample.ast.codegen.sample;

import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.RecursiveTask;
import java.util.concurrent.atomic.AtomicInteger;

public class FiboForkJoin extends RecursiveTask<Long> {

	private static final long serialVersionUID = 1L;

	private final long n;

	private static final AtomicInteger threads = new AtomicInteger();

	FiboForkJoin(long n) {
		this.n = n;
	}

	@Override
	public Long compute() {
		return fib(n);
	}

	public long fib(long n) {
		if (n <= 1) {
			return n;
		}

		if (threads.intValue() < 8) {
			threads.incrementAndGet();
			// --
			FiboForkJoin f1 = new FiboForkJoin(n - 1);
			f1.fork();
			FiboForkJoin f2 = new FiboForkJoin(n - 2);
			long value = f2.compute() + f1.join();
			// --
			threads.decrementAndGet();
			return value;
		} else {
			return (fib(n - 2) + fib(n - 1));
		}
	}

	public static void main(String[] args) throws Exception {
		long start = System.currentTimeMillis();

		ForkJoinPool pool = new ForkJoinPool();
		FiboForkJoin task = new FiboForkJoin(50);
		pool.execute(task);
		System.out.println(task.join());
		System.out.println("duration: " + (System.currentTimeMillis() - start));
	}
}